import { isArray, isFunction, isNumber, isString, isUndefined } from '../is';
import { newError } from '../utils';
import { PluginInterface, PluginBaseProps } from './defined/plugins';
import { PluginType } from './index';

/**
 * 插件验证器 - 增强版本
 */
export class PluginValidator {
  /**
   * 验证插件基础属性
   */
  static validateBaseProps(plugin: PluginInterface): void {
    // ID 验证
    if (isUndefined(plugin.ID)) {
      throw newError('Static property [ID] not found');
    }
    if (!isString(plugin.ID)) {
      throw newError('Static property [ID] is not of string type');
    }
    if (!/^[A-Za-z0-9_\-]+$/.test(plugin.ID) || plugin.ID.trim() !== plugin.ID) {
      throw newError('The ID format is not standard. Only alphanumeric, underscore and dash are allowed');
    }
    if (plugin.ID.length < 8 || plugin.ID.length > 64) {
      throw newError(`Static property [ID] Length:${plugin.ID.length}, ID range in length [8,64]`);
    }

    // TYPE 验证
    if (isUndefined(plugin.TYPE)) {
      throw newError('Static property [TYPE] not found');
    }
    if (!isNumber(plugin.TYPE)) {
      throw newError('Static property [TYPE] is not of number type');
    }
    if (isUndefined(PluginType.valueOf(plugin.TYPE))) {
      throw newError('Static property [TYPE] is unknown plugin type');
    }

    // GROUP 验证
    if (isUndefined(plugin.GROUP)) {
      throw newError('Static property [GROUP] not found');
    }
    if (!isString(plugin.GROUP)) {
      throw newError('Static property [GROUP] is not of string type');
    }
    if (plugin.GROUP.trim() !== plugin.GROUP) {
      throw newError('The GROUP format is not standard');
    }
    if (plugin.GROUP.length < 1 || plugin.GROUP.length > 20) {
      throw newError(`Static property [GROUP] Length:${plugin.GROUP.length}, GROUP range in length [1,20]`);
    }

    // NAME 验证
    if (isUndefined(plugin.NAME)) {
      throw newError('Static property [NAME] not found');
    }
    if (!isString(plugin.NAME)) {
      throw newError('Static property [NAME] is not of string type');
    }
    if (plugin.NAME.trim() !== plugin.NAME) {
      throw newError('The NAME format is not standard');
    }
    if (plugin.NAME.length < 1 || plugin.NAME.length > 30) {
      throw newError(`Static property [NAME] Length:${plugin.NAME.length}, NAME range in length [1,30]`);
    }

    // VERSION 验证
    if (isUndefined(plugin.VERSION)) {
      throw newError('Static property [VERSION] not found');
    }
    if (!isString(plugin.VERSION)) {
      throw newError('Static property [VERSION] is not of string type');
    }
    if (plugin.VERSION.trim() !== plugin.VERSION) {
      throw newError('The VERSION format is not standard');
    }
    if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?$/.test(plugin.VERSION)) {
      throw newError('The VERSION format should be semantic version (e.g., 1.0.0, 1.0.0-beta)');
    }

    // VERSION_CODE 验证
    if (isUndefined(plugin.VERSION_CODE)) {
      throw newError('Static property [VERSION_CODE] not found');
    }
    if (!isNumber(plugin.VERSION_CODE) || plugin.VERSION_CODE < 1) {
      throw newError('Static property [VERSION_CODE] must be a positive number');
    }

    // PLUGIN_FILE_URL 验证
    if (isUndefined(plugin.PLUGIN_FILE_URL)) {
      throw newError('Static property [PLUGIN_FILE_URL] not found');
    }
    if (!isString(plugin.PLUGIN_FILE_URL)) {
      throw newError('Static property [PLUGIN_FILE_URL] is not of string type');
    }
    if (plugin.PLUGIN_FILE_URL.trim() && !/^https?:\/\/.*?\.js$/i.test(plugin.PLUGIN_FILE_URL)) {
      throw newError('The [PLUGIN_FILE_URL] format is not standard');
    }

    // BASE_URL 验证（书源和书城插件需要）
    if ([PluginType.BOOK_SOURCE, PluginType.BOOK_STORE].includes(plugin.TYPE)) {
      if (isUndefined(plugin.BASE_URL)) {
        throw newError('Static property [BASE_URL] not found');
      }
      if (!isString(plugin.BASE_URL)) {
        throw newError('Static property [BASE_URL] is not of string type');
      }
      if (!plugin.BASE_URL.trim()) {
        throw newError('Static property [BASE_URL] is empty');
      }
      if (!/^https?:\/\/.*?/i.test(plugin.BASE_URL)) {
        throw newError('The [BASE_URL] format is not standard');
      }
    }
  }

  /**
   * 验证插件依赖
   */
  static validateDependencies(plugin: PluginInterface): void {
    if (plugin.REQUIRE) {
      for (const [key, value] of Object.entries(plugin.REQUIRE)) {
        if (!isString(key) || key.trim() !== key || key.length === 0) {
          throw newError(`Invalid REQUIRE key: ${key}`);
        }
        
        // 支持新版本插件配置格式
        if (typeof value === 'object' && value !== null) {
          const requireItem = value as any;
          if (!requireItem.type || !['number', 'string', 'list', 'password', 'boolean'].includes(requireItem.type)) {
            throw newError(`Invalid REQUIRE type for key ${key}: ${requireItem.type}`);
          }
          if (isUndefined(requireItem.default)) {
            throw newError(`Missing default value for REQUIRE key: ${key}`);
          }
        }
      }
    }
  }

  /**
   * 验证插件安全性
   */
  static validateSecurity(jscode: string): void {
    // 检查危险函数调用
    const dangerousPatterns = [
      /eval\s*\(/,
      /Function\s*\(/,
      /setTimeout\s*\(\s*["'`][^"'`]*["'`]/,
      /setInterval\s*\(\s*["'`][^"'`]*["'`]/,
      /document\./,
      /window\./,
      /global\./,
      /process\./,
      /require\s*\(/,
      /import\s+.*\s+from/,
      /fs\./,
      /child_process/,
      /exec\s*\(/,
      /spawn\s*\(/,
    ];

    for (const pattern of dangerousPatterns) {
      if (pattern.test(jscode)) {
        throw newError(`Potentially dangerous code detected: ${pattern.source}`);
      }
    }

    // 检查代码长度
    if (jscode.length > 1024 * 1024) { // 1MB 限制
      throw newError('Plugin code is too large (max 1MB)');
    }
  }

  /**
   * 验证插件性能
   */
  static validatePerformance(plugin: PluginInterface): void {
    // 检查方法数量
    const methods = Object.getOwnPropertyNames(plugin.prototype).filter(name => 
      isFunction((plugin.prototype as any)[name]) && name !== 'constructor',
    );
    
    if (methods.length > 50) {
      throw newError('Plugin has too many methods (max 50)');
    }
  }

  /**
   * 完整验证插件
   */
  static validate(plugin: PluginInterface, jscode?: string): void {
    this.validateBaseProps(plugin);
    this.validateDependencies(plugin);
    this.validatePerformance(plugin);
    
    if (jscode) {
      this.validateSecurity(jscode);
    }
  }
}